package com.sixtyplus.semen.boardapp.board.serialport;

import java.util.Locale;

public class HexUtil {
	private final static char[] mChars = "0123456789ABCDEF".toCharArray();
	private final static String mHexStr = "0123456789ABCDEF";
    private static int defaultLength = 4;

	/**  
     * 字符串转换成十六进制字符串 
     * @param str 待转换的ASCII字符串
     * @return String 每个Byte之间空格分隔
     * @example "12345ab"——>"31 32 33 34 35 61 62"
     */    
    public static String str2HexStr(String str){    
        StringBuilder sb = new StringBuilder();  
        byte[] bs = str.getBytes();    
          
        for (int i = 0; i < bs.length; i++){    
            sb.append(mChars[(bs[i] & 0xFF) >> 4]);    
            sb.append(mChars[bs[i] & 0x0F]);  
            sb.append(' ');  
        }    
        return sb.toString().trim();    
    }  
      
    /**  
     * 十六进制字符串转换成 ASCII字符串 
     * @param hexStr Byte字符串 
     * @return String 对应的字符串 
     * @example "31 32 33 34 35 61 62"——>"12345ab"
     */    
    public static String hexStr2Str(String hexStr){    
        hexStr = hexStr.toString().trim().replace(" ", "").toUpperCase(Locale.US);
        char[] hexs = hexStr.toCharArray();    
        byte[] bytes = new byte[hexStr.length() / 2];    
        int iTmp = 0x00;;    
  
        for (int i = 0; i < bytes.length; i++){    
            iTmp = mHexStr.indexOf(hexs[2 * i]) << 4;    
            iTmp |= mHexStr.indexOf(hexs[2 * i + 1]);    
            bytes[i] = (byte) (iTmp & 0xFF);    
        }    
        return new String(bytes);    
    }  
    
    /** 
     * bytes转换成十六进制字符串 
     * @param b byte数组  byte(-128 127)
     * @param iLen 取前N位处理
     * @return String 每个Byte值之间空格分隔 
     * @example {1,2,11,12,127}——>"01 02 0B 0C 7F"
     */  
    public static String byte2HexStr(byte[] b, int iLen){  
        StringBuilder sb = new StringBuilder();  
        iLen = b.length;
        for (int n=0; n<iLen; n++){  
            sb.append(mChars[(b[n] & 0xFF) >> 4]);  
            sb.append(mChars[b[n] & 0x0F]);  
            sb.append(' ');  
        }  
        return sb.toString().trim().toUpperCase(Locale.US);  
    }  
    
    /** 
     * bytes字符串转换为Byte值 
     * @param src String
     * @return byte[]
     * @example "01 02 0B 0C 7F"——>{1,2,11,12,127}
     */  
    public static byte[] hexStr2Bytes(String src){  
        src = src.trim().replace(" ", "").toUpperCase(Locale.US);  
        int m=0,n=0;  
        int iLen=src.length()/2; //计算长度  
        byte[] ret = new byte[iLen]; //分配存储空间  
          
        for (int i = 0; i < iLen; i++){  
            m=i*2+1;  
            n=m+1;  
            ret[i] = (byte)(Integer.decode("0x"+ src.substring(i*2, m) + src.substring(m,n)).intValue() & 0xFF); 
        }  
        return ret;  
    }

    public static int decode(byte[] bytes, boolean signed) {
        if (bytes.length == 0) {
            return 0;
        }
        int length = bytes.length;
        boolean minus = false;
        if (signed) {
            minus = (bytes[bytes.length - 1] >> 7 & 1) == 1; // 判断是否是负数
        }
        int value = 0;

        for (int i = 0; i < bytes.length; i++) {
            value = value | (bytes[i] & 0xFF) << (8 * i);
        }
        if (minus) { // 负数进行补位
            for (int j = length; j < defaultLength; j++) {
                value = value | 0xFF << (8 * j);
            }
        }

        return value;
    }

    public static int decode(byte[] bytes, int start, int offset) {
        if (bytes.length < (start + offset)) {
            return 0;
        }

        int value = 0;
        for (int i = start; i < start + offset; i++) {
            value = value | (bytes[i] & 0xFF) << (8 * (offset - 1 - (i - start)));
        }

        return value;
    }

    /**
     * 计算CRC16校验码
     *
     * @param bytes
     * @return
     */
    public static int getCRC16(byte[] bytes, int len) {
        int crc16 = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;
        for (int i = 0; i < len; i++) {
            crc16 ^= ((int) bytes[i] & 0x000000ff);
            for (int j = 0; j < 8; j++) {
                if ((crc16 & 0x00000001) != 0) {
                    crc16 >>= 1;
                    crc16 ^= POLYNOMIAL;
                } else {
                    crc16 >>= 1;
                }
            }
        }
//        return Integer.toHexString(crc16);
        return crc16;
    }
}
